package org.custom.ibatis.session;

import java.lang.reflect.Method;
import java.sql.*;

/**
 * @author DJJ_F
 * @version 1.0
 * @date 2025/02/25
 * @description 他使用连接对象，执行sql语句
 * 所以需要传入TransactionManager和mappers
 * 同时对外提供各种方法
 * 同时sqlSession自己也有close,commit,rollback方法
 */
public class SqlSession {
    private SqlSessionFactory factory;

    public SqlSession(SqlSessionFactory sqlSessionFactory) {
        this.factory = sqlSessionFactory;
    }

    /**
     * 调用connection对象，执行sql语句
     *
     * @param sqlId
     * @param pojo
     * @return
     */
    public int insert(String sqlId, Object pojo) {
        int count = 0;
        try {
            Connection connection = factory.getTxManager().getConnection();
            // 获取sql语句
            String statement = factory.getMappers().get(sqlId).getSql();
            // 将#{}替换成?, 使用正则表达式
            String newStatement = statement.replaceAll("#\\{[0-9a-zA-z_$]*}", "?");
            PreparedStatement ps = connection.prepareStatement(newStatement);
            // 这里需要给?号赋值
            int fromIndex = 0, cnt = 0;
            while (true) {
                int startIndex = statement.indexOf('#', fromIndex);
                if (startIndex < 0) break;
                cnt++;
                int endIndex = statement.indexOf('}', fromIndex);
                String property = statement.substring(startIndex + 2, endIndex);
                Class<?> clazz = pojo.getClass();
                String getMethodName = "get" + property.toUpperCase().charAt(0) + property.substring(1);
                Method getMethod = clazz.getDeclaredMethod(getMethodName);
                Object field = getMethod.invoke(pojo);
                fromIndex = endIndex + 1;
                ps.setString(cnt, field.toString());
            }
            // 增删改都是executeUpdate
            count = ps.executeUpdate();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        return count;
    }

    public Object selectOne(String sqlId, Object param) {
        Object resultObj = null;
        try {
            Connection connection = factory.getTxManager().getConnection();
            MapperStatement mapperStatement = factory.getMappers().get(sqlId);

            String newStatement = mapperStatement.getSql().replaceAll("#\\{[0-9a-zA-Z_$]*}", "?");
            PreparedStatement ps = connection.prepareStatement(newStatement);

            // 要开始处理参数了, 这里假定就一个参数, 直接传就行了
            ps.setString(1, param.toString());

            // 要执行sql语句, 处理结果集
            ResultSet resultSet = ps.executeQuery();

            // 如果查询到了结果
            if(resultSet.next()) {
                Class<?> clazz = Class.forName(mapperStatement.getResultType());
                resultObj = clazz.getDeclaredConstructor().newInstance();
                // 获取源数据的封装对象
                ResultSetMetaData metaData = resultSet.getMetaData();
                // 获取字段数量
                int columnCount = metaData.getColumnCount();
                for (int i = 0; i < columnCount; i++) {
                    // 获取字段的别名，getColumnName是获取原名，注意从1开始
                    String columnLabel = metaData.getColumnLabel(i + 1);
                    String setMethodName = "set" + columnLabel.toUpperCase().charAt(0) + columnLabel.substring(1);
                    // 这里需要传入String.class 指定方法的类型
                    Method setMethod = clazz.getDeclaredMethod(setMethodName, String.class);
                    setMethod.invoke(resultObj, resultSet.getString(columnLabel));
                }
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        return resultObj;
    }

    public void commit() {
        this.factory.getTxManager().commit();
    }

    public void rollback() {
        this.factory.getTxManager().rollback();
    }

    public void close() {
        this.factory.getTxManager().close();
    }
}
